package com.baidu.iit.pvm.process;

import com.baidu.iit.pvm.PvmException;
import com.baidu.iit.pvm.PvmScope;
import com.baidu.iit.pvm.delegate.ExecutionListener;

import java.util.*;

/**
 * 流程单元实现类
 * Created by 卫立 on 2014/4/7.
 */
public abstract class ScopeImpl extends ProcessElementImpl implements PvmScope {

    //节点定义
    protected List<ActivityImpl> activities = new ArrayList<ActivityImpl>();

    //节点映射
    protected Map<String, ActivityImpl> namedActivities = new HashMap<String, ActivityImpl>();

    //事件监听对象
    protected Map<String, List<ExecutionListener>> executionListeners = new HashMap<String, List<ExecutionListener>>();

    /**
     * 构造
     * @param id
     * @param processDefinition
     */
    public ScopeImpl(String id, ProcessDefinitionImpl processDefinition) {
        super(id, processDefinition);
    }


    /**
     * 根据Id获 节点内容
     * @param activityId
     * @return
     */
    public ActivityImpl findActivity(String activityId) {
        //通过名称获取外网的节点，不是单元节点的情况
        ActivityImpl localActivity = namedActivities.get(activityId);
        if (localActivity != null) {
            return localActivity;
        }
        //遍历节点
        for (ActivityImpl activity : activities) {
            //查找单元内的节点对象
            ActivityImpl nestedActivity = activity.findActivity(activityId);
            if (nestedActivity != null) {
                return nestedActivity;
            }
        }
        return null;
    }


    /**
     * 创建节点信息
     * @return
     */
    public ActivityImpl createActivity() {
        return createActivity(null);
    }

    /**
     * 根据ID创建节点信息
     * @param activityId
     * @return
     */
    public ActivityImpl createActivity(String activityId) {
        ActivityImpl activity = new ActivityImpl(activityId, processDefinition);
        //当ID不为空的时候进行重复性判断
        if (activityId != null) {
            if (processDefinition.findActivity(activityId) != null) {
                throw new PvmException("duplicate activity id '" + activityId + "'");
            }
            namedActivities.put(activityId, activity);
        }
        //设置当前节点为新节点的父级节点
        activity.setParent(this);
        activities.add(activity);
        return activity;
    }

    /**
     * 判断是否包含某个节点
     * @param activity
     * @return
     */
    public boolean contains(ActivityImpl activity) {
        if (namedActivities.containsKey(activity.getId())) {
            return true;
        }

        //单元节点内判断
        for (ActivityImpl nestedActivity : activities) {
            if (nestedActivity.contains(activity)) {
                return true;
            }
        }
        return false;
    }


    /**
     * 根据事件名称获取相关的监听事件
     * @param eventName
     * @return
     */
    public List<ExecutionListener> getExecutionListeners(String eventName) {
        List<ExecutionListener> executionListenerList = getExecutionListeners().get(eventName);
        if (executionListenerList != null) {
            return executionListenerList;
        }
        return Collections.EMPTY_LIST;
    }

    /**
     * 添加监听的事件
     * @param eventName 事件的名称
     * @param executionListener 监听动作
     */
    public void addExecutionListener(String eventName, ExecutionListener executionListener) {
        addExecutionListener(eventName, executionListener, -1);
    }

    /**
     * 添加监听的事件
     * @param eventName     事件的名称
     * @param executionListener     监听的动作
     * @param index       插入的位置，当小余0的时候插入到末尾
     */
    public void addExecutionListener(String eventName, ExecutionListener executionListener, int index) {
        List<ExecutionListener> listeners = executionListeners.get(eventName);
        if (listeners == null) {
            listeners = new ArrayList<ExecutionListener>();
            executionListeners.put(eventName, listeners);
        }
        if (index < 0) {
            listeners.add(executionListener);
        } else {
            listeners.add(index, executionListener);
        }
    }

    /**
     * 获取所有的监听
     * @return
     */
    public Map<String, List<ExecutionListener>> getExecutionListeners() {
        return executionListeners;
    }


    /**
     * 获取所有的节点
     * @return
     */
    public List<ActivityImpl> getActivities() {
        return activities;
    }


}
